package com.szsh.aiot.framework.aspectj;

import com.google.gson.Gson;
import com.szsh.aiot.common.annotation.Log;
import com.szsh.aiot.common.core.domain.AjaxResult;
import com.szsh.aiot.framework.constant.Constants;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

/**
 * 操作日志记录处理
 */
@Aspect
@Component
@Order(1)
public class LogAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);

    private final Gson gson;

    public LogAspect(Gson gson) {
        this.gson = gson;
    }

    /**
     * 处理日志注解
     * @param joinPoint 切点
     */
    @Around(value = "@annotation(com.szsh.aiot.common.annotation.Log) && @annotation(controllerLog)")
    public Object around(ProceedingJoinPoint joinPoint, Log controllerLog) {
        MDC.put(Constants.LOG_PREFIX, controllerLog.title());

        // 获取参数
        Object[] args = joinPoint.getArgs();
        // 需要打印的参数列表(去除HttpServletRequest/HttpServletResponse/HttpSession)
        List<Object> printParameterList = new ArrayList<>();
        for (Object obj : args) {
            if (null == obj) {
                continue;
            }
            if (HttpServletRequest.class.isAssignableFrom(obj.getClass())) {
                continue;
            }
            if (HttpServletResponse.class.isAssignableFrom(obj.getClass())) {
                continue;
            }
            if (HttpSession.class.isAssignableFrom(obj.getClass())) {
                continue;
            }
            printParameterList.add(obj);
        }

        if (LOGGER.isInfoEnabled()) {
            // 打印请求参数
            if (controllerLog.isPrintRequestData()) {
                LOGGER.info("[开始]{}", gson.toJson(printParameterList));
            } else {
                LOGGER.info("[开始]");
                printParameterList.clear();
            }
        }

        Object returnObject = null;
        try {
            // 执行方法
            returnObject = joinPoint.proceed();
        } catch (Throwable e) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("[系统异常]", e);
            }

            Signature signature = joinPoint.getSignature();
            if (signature instanceof MethodSignature) {
                Class<?> methodReturnType = ((MethodSignature) signature).getReturnType();
                if (AjaxResult.class.isAssignableFrom(methodReturnType)) {
                    // 返回 AjaxResult 类型
                    returnObject = AjaxResult.error();
                }
            }
        }

        if (LOGGER.isInfoEnabled()) {
            if (controllerLog.isPrintResponseData()) {
                // 打印返回参数
                LOGGER.info("[结束][{}]", gson.toJson(returnObject));
            } else {
                LOGGER.info("[结束]");
            }
        }
        return returnObject;
    }
}
